package com.lzc.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.lzc.common.ImCache;
import com.lzc.mapper.UserMapper;
import com.lzc.pojo.dto.UserDto;
import com.lzc.pojo.dto.WxToken;
import com.lzc.pojo.dto.WxUser;
import com.lzc.pojo.entity.User;
import com.lzc.pojo.vo.Result;
import com.lzc.pojo.vo.UserLoginVo;
import com.lzc.pojo.vo.UserRegisterVo;
import com.lzc.service.LoginService;
import com.lzc.util.JwtUtil;
import com.lzc.util.RedisKey;
import com.lzc.util.ThreadLocalUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;


@Service
@SuppressWarnings("all")
public class LoginServiceImpl implements LoginService {

    @Autowired
    private QrConfig qrConfig;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ImCache cache;

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.appsecret}")
    private String appsecret;

    @Value("${wx.callback}")
    private String callBack;


    /**
     * 生成微信二维码返回给前端
     */
    @Override
    public void createWxLoginCode(String uuid, HttpServletResponse response) throws IOException {

        // 设置返回类型
        response.setContentType("image/png");
        // 获取输出流
        ServletOutputStream outputStream = response.getOutputStream();

        // 创建微信二维码访问地址
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
                "appid="+appid+
                "&redirect_uri="+callBack+
                "&response_type=code" +
                "&scope=snsapi_userinfo" +
                "&state="+uuid+"#wechat_redirect";

        // 返回二维码图片
        QrCodeUtil.generate(url,qrConfig,"png",outputStream);

    }


    /**
     * 获取微信用户数据
     * @param code code
     * @param uuid uuid
     */
    @Override
    public void loginWxUser(String code, String uuid) {

        // 返回给前端的jwt令牌
        String jwt;

        // 生成获取openid和access_token的url
        String urlGetToken = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid="+appid+
                "&secret="+appsecret+
                "&code="+code+
                "&grant_type=authorization_code";

        // 发起请求
        String wxTokenStr = restTemplate.getForObject(urlGetToken, String.class);

        // 得到wxToken数据
        WxToken wxToken = JSONUtil.toBean(wxTokenStr, WxToken.class);

        // 获取openid和access_token
        String openid = wxToken.getOpenid();
        String access_token = wxToken.getAccess_token();

        // 根据openid查询数据库
        User user = getUserByOpenId(openid);
        if (user != null){

            // 如果数据库中有数据则生成jwt令牌
            jwt = JwtUtil.createJwt(user.getId());

        }else {

            // 数据库没有数据，生成获取用户信息的url
            String urlGetUser = "https://api.weixin.qq.com/sns/userinfo?" +
                    "access_token="+access_token+
                    "&openid="+openid+
                    "&lang=zh_CN;";

            // 得到微信用户信息
            String userStr = restTemplate.getForObject(urlGetUser, String.class);
            WxUser wxUser = JSONUtil.toBean(userStr, WxUser.class);

            // 微信用户转为系统用户存入数据库
            User sysUser = wxTosysUser(wxUser);

            // 存入数据库
            userMapper.insert(sysUser);

            // 生成jwt
            jwt = JwtUtil.createJwt(sysUser.getId());

        }

        // 如果jwt不为空则以uuid为key  jwt为value存入caffeine
        if (StrUtil.isNotBlank(jwt)){

            cache.set(RedisKey.UUID_KEY+uuid,jwt);

        }


    }

    /**
     * 系统用户登陆
     * @param userVo 账号和密码
     * @return
     */
    @Override
    public Result loginSysUser(UserLoginVo userLoginVo) {

        // 获取用户名密码
        String username = userLoginVo.getUsername();
        String password = userLoginVo.getPassword();

        if (StrUtil.isBlank(username) || StrUtil.isBlank(password)){
            return Result.FILE("账号或密码不能为空！！");
        }

        // 根据用户名查询用户
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));

        if (user == null){
            return Result.FILE("账号不存在！！");
        }

        if (!password.equals(user.getPassword())){
            return Result.FILE("密码错误！！");
        }
        if (user.getState() == 0){
            return Result.FILE("账号已被注销！！");
        }

        // 生成jwt令牌
        String jwt = JwtUtil.createJwt(user.getId());

        return Result.OK(jwt);
    }


    /**
     * 系统用户注册
     * @param userRegisterVo 注册信息
     * @return
     */
    @Override
    public Result registerSysUser(UserRegisterVo userRegisterVo) {

        // 数据校验
        String nickname = userRegisterVo.getNickname();
        Character sex = userRegisterVo.getSex();
        String password = userRegisterVo.getPassword();
        String image = userRegisterVo.getImage();
        String username = userRegisterVo.getUsername();

        if (StrUtil.isBlank(nickname)){
            return Result.FILE("昵称不能为空！！");
        }
        if (StrUtil.isBlank(sex.toString())){
            return Result.FILE("性别不能为空！！");
        }
        if (StrUtil.isBlank(password)){
            return Result.FILE("密码不能为空！！");
        }
        if (StrUtil.isBlank(image)){
            image = "";
        }
        if (StrUtil.isBlank(username)) {
            return Result.FILE("账号不能为空");
        }
        if (!username.matches("^[a-zA-Z0-9_]+$") || username.length() > 10){
            return Result.FILE("账号只能为英文,数字且长度不能大于10");
        }

        // 判断账号是否唯一
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        if (user != null){
            return Result.FILE("该账号已经被使用 ! ! ");
        }

        user = new User();

        // 属性拷贝
        BeanUtils.copyProperties(userRegisterVo, user);

        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setState((byte) 1);

        // 存入数据库
        userMapper.insert(user);

        return Result.OK(null);
    }

    /**
     * 根据uuid获取令牌
     * @param uuid uuid
     * @return
     */
    @Override
    public Result getJwt(String uuid) {
        String jwt = cache.getString(RedisKey.UUID_KEY+uuid);
        if (StrUtil.isBlank(jwt)){
            return Result.OK(null);
        }
        cache.remove(RedisKey.UUID_KEY+uuid);
        return Result.OK(jwt) ;
    }

    /**
     * 根据openid查询数据库
     * @param openId
     * @return
     */
    private User getUserByOpenId(String openId){
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenId, openId));
        return user;
    }


    /**
     * 微信用户转系统用户
     * @param wxUser
     * @return
     */
    private User wxTosysUser(WxUser wxUser){

        User sysUser = new User();

        sysUser.setOpenId(wxUser.getOpenid());

        sysUser.setNickname(wxUser.getNickname());

        sysUser.setImage(wxUser.getHeadimgurl());

        if (wxUser.getSex() == 1){

            sysUser.setSex('男');

        }else if (wxUser.getSex() == 2){

            sysUser.setSex('女');

        }

        sysUser.setUsername(wxUser.getOpenid().substring(0,10));

        sysUser.setPassword("123456");

        sysUser.setState((byte) 1);

        sysUser.setCreateTime(LocalDateTime.now());

        sysUser.setUpdateTime(LocalDateTime.now());

        return sysUser;

    }
}